package mrusanov.league

import collection.mutable.ArrayBuffer
import mrusanov.team.{ TeamLevel, Club, Team }
import util.Random

object LeagueSystem {

	// clubs are sorted from strongest to weakest
	def initLeagueSystem(year: Int, infoSystem: LeagueInfoSystem, clubs: Vector[Club], teamLevel: TeamLevel): LeagueSystem = {
		var remainingClubs = clubs
		var leagues: List[League] = Nil

		for (
			lvl <- 0 until infoSystem.levels;
			lg <- 0 until infoSystem.leagues(lvl).leagues
		) {

			val clubsInThisLeagueCount = infoSystem.leagues(lvl).teams
			val clubs = remainingClubs.take(clubsInThisLeagueCount).map(_.team(teamLevel))
			remainingClubs = remainingClubs.drop(clubsInThisLeagueCount)
			// TODO generate names in 2nd position
			leagues ::= new League(clubs, lvl.toString + " league", infoSystem, lvl, year)
		}

		leagues = leagues.reverse

		new LeagueSystem(year, infoSystem, Vector() ++ leagues, teamLevel)
	}
}

class LeagueSystem private (val year: Int, infoSystem: LeagueInfoSystem, val leagues: Vector[League], val teamLevel: TeamLevel) {

	def buildNextSeasonLeagueSystem: LeagueSystem = {
		var promoted: ArrayBuffer[Vector[Team]] = ArrayBuffer()
		var relegated: ArrayBuffer[Vector[Team]] = ArrayBuffer()
		var notChanged: ArrayBuffer[Vector[Team]] = ArrayBuffer()

		for (i <- 0.until(infoSystem.levels)) {
			promoted += Random.shuffle(leaguesOfLevel(i).map(_.promoted).flatten)
			relegated += Random.shuffle(leaguesOfLevel(i).map(_.relegated).flatten)
			notChanged += Random.shuffle(leaguesOfLevel(i).map(_.notChangedLeague).flatten)
		}

		promoted = promoted.drop(1) :+ Vector()

		relegated = (relegated.+:(Vector())).init

		val newLeaguesArr = ArrayBuffer[(Vector[Team], Int)]()
		for (lvl <- 0 until infoSystem.levels; lgs <- 0 until infoSystem.leagues(lvl).leagues) {
			val totalLeagues = infoSystem.leagues(lvl).leagues
			val promotedToThisLeagueCount = promoted(lvl).size / totalLeagues
			val relegatedToThisLeagueCount = relegated(lvl).size / totalLeagues
			val notChangedCount = notChanged(lvl).size / totalLeagues

			val newTeams = promoted(lvl).slice(lgs * promotedToThisLeagueCount,
				(lgs + 1) * promotedToThisLeagueCount) ++
				relegated(lvl).slice(lgs * relegatedToThisLeagueCount,
					(lgs + 1) * relegatedToThisLeagueCount) ++
					notChanged(lvl).slice(lgs * notChangedCount,
						(lgs + 1) * notChangedCount)

			newLeaguesArr.+=((newTeams, lvl))
		}

		// TODO generate names
		val newLeagues = Vector() ++ newLeaguesArr.map(lg => new League(lg._1, "", infoSystem, lg._2, year))
		val newYear = year + 1
		new LeagueSystem(newYear, infoSystem, newLeagues, teamLevel)
	}

	private def leaguesOfLevel(level: Int) = leagues.filter(_.info.level == level)
	def leagueOfTeam(team: Team) = leagues.filter(_.teams.contains(team))(0)
}
